﻿using System;
using System.Web.UI;
using InfoJetSoft.Service;
using Microsoft.SharePoint.Workflow;
using ServBus.ListForm2010.Extension;
using System.Xml;
using Microsoft.SharePoint;
using System.Collections.Generic;
using ServBus.ListForm2010.Utility;
using System.Diagnostics;
using System.Xml.XPath;
using System.Web;
using InfoJetSoft.Service.Util;
using System.Collections;
using System.Globalization;

namespace ServBus.ListForm2010.ApplicationPages
{
    public partial class xdoc : System.Web.UI.Page
    {
        protected override void Render(HtmlTextWriter output)
        {
            try
            {
                string publishUrl = this.Context.Request["xdoc_param_xsn_uri"];
                RelativeUrlResolver resolver = new RelativeUrlResolver(publishUrl);
                InfoJetContext ijCtx = new InfoJetContext();
                ijCtx.InlineFileStorage = new InlineFileStorage();
                ijCtx.RelativeUrlResolver = resolver;
                //Register SubmitToHost
                ijCtx.SubmitToListFormHostEvent += jetContext_SubmitToListFormHostEvent;
                InfoJetForm form = null;
                if (InfoJetService.IsFormSessionDataLost(this.Context))
                {
                    form = InfoJetService.RecoverForm(this.Context, ijCtx);
                }
                else
                {
                    form = InfoJetService.UpdateForm(this.Context, ijCtx);
                }
                output.Write(form.Xhtml);
                output.Close();
            }
            catch (Exception e)
            {
                output.Write(e.Message + "<br>");
                output.Write(e.StackTrace);
                output.Close();
            }
        }

        protected void jetContext_SubmitToListFormHostEvent(InfoJetSoft.Service.Entity.Form form, InfoJetSoft.Service.Entity.SubmitToHostAdapter submitToHostAdapter)
        {
            Initial();
            //Debug.WriteLine("submit " + submitToHostAdapter.Name);
            if (string.IsNullOrEmpty(submitToHostAdapter.Name))
            {
                //Response.Write("You click cancel!");
            }
            else
            {
                SaveForm(form, submitToHostAdapter.Name);
            }
        }

        #region Parameters

        private static string _siteName;//"http://win-3ststb2hjp7";
        private static Guid _webName;//"Test";
        private static string _listId = "";//"test";
        private static string _ctypeId = "";
        private static string _itemId = "";//string.Empty;
        private static string _viewId = "";//string.Empty;
        private static string _xsnLocation = "";
        private static string _errorMsg = "";
        //private static string InfojetServiceAction = "/_layouts/ListForm2010/xdoc.aspx";
        private static string _ctypeName = "";

        private static readonly Dictionary<string, Dictionary<int, string>> SItemsId = new Dictionary<string, Dictionary<int, string>>();

        private static XmlNamespaceManager _xNameSpace;

        #endregion
        protected void Initial()
        {
            _listId = HttpUtility.ParseQueryString(Context.Request.UrlReferrer.Query)["listId"];
            _ctypeId = HttpUtility.ParseQueryString(Context.Request.UrlReferrer.Query)["ctype"];
            _itemId = HttpUtility.ParseQueryString(Context.Request.UrlReferrer.Query)["itemId"];
            //viewId = Context.Request["view"];
            _siteName = SPContext.Current.Site.Url;

            _webName = SPContext.Current.Web.ID;

            _xNameSpace = new XmlNamespaceManager(new NameTable());
            _xNameSpace.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
            _xNameSpace.AddNamespace("tns", "http://tempuri.org/");
            _xNameSpace.AddNamespace("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
        }

        protected void SaveForm(InfoJetSoft.Service.Entity.Form form, string submitToHostAdapterName)
        {
            try
            {
                _listId = HttpUtility.ParseQueryString(Context.Request.UrlReferrer.Query)["listId"];
                _ctypeId = HttpUtility.ParseQueryString(Context.Request.UrlReferrer.Query)["ctype"];
                _itemId = HttpUtility.ParseQueryString(Context.Request.UrlReferrer.Query)["itemId"];
                //viewId = Context.Request["view"];
                _siteName = SPContext.Current.Site.Url;

                _webName = SPContext.Current.Web.ID;

                _xNameSpace = new XmlNamespaceManager(new NameTable());
                _xNameSpace.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
                _xNameSpace.AddNamespace("tns", "http://tempuri.org/");
                _xNameSpace.AddNamespace("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");

                JetIdCache idCache = new JetIdCache(form.XmlDoc.DocumentElement);
                string xml = DOMUtil.toString(form.XmlDoc);
                idCache.reset();
                XmlDocument xDoc = form.XmlDoc;

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            web.AllowUnsafeUpdates = true;
                            SPList list = web.Lists[new Guid(_listId)];
                            SPContentTypeId contentTypeId = new SPContentTypeId(_ctypeId.ToLower());
                            _ctypeName = list.ContentTypes[contentTypeId].Name;
                            int itemId = 0;

                            itemId = Convert.ToInt32(_itemId);

                            SPListItem item = list.GetItemById(itemId);
                            //unlock the task
                            item[SPBuiltInFieldId.WorkflowVersion] = 1;
                            item.SystemUpdate();
                            foreach (XmlNode xNode in xDoc.ChildNodes)
                            {
                                SaveListFieldsValue(xNode, list, item);
                            }
                            Hashtable ht = new Hashtable();
                            ht[SPBuiltInFieldId.Completed] = "TRUE";
                            ht["Completed"] = "TRUE";
                            ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
                            ht["PercentComplete"] = 1.0f;
                            ht["Status"] = "Completed";
                            ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)item.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);

                            ht[SPBuiltInFieldId.WorkflowOutcome] = submitToHostAdapterName;
                            ht["TaskStatus"] = "Approved";
                            ht["FormData"] = SPWorkflowStatus.Completed;
                            //ht["ows_FieldName_Comments"] = "Approver comments will be here";

                            bool alterstatus = true;
                            while (!(alterstatus = SPWorkflowTask.AlterTask(item, ht, true)))
                            {
                                System.Threading.Thread.Sleep(1000);
                                alterstatus = SPWorkflowTask.AlterTask(item, ht, true);
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                ErrorLog.Write(ex.ToString(), EventLogEntryType.Error);
            }
        }

        #region Private Method
        private void SaveListFieldsValue(XmlNode xNode, SPList plist, SPListItem p_Item)
        {
            if (xNode.LocalName != "SubForms")
            {
                if (xNode.HasChildNodes)
                {
                    foreach (XmlNode cXNode in xNode.ChildNodes)
                    {
                        SaveListFieldsValue(cXNode, plist, p_Item);
                    }
                }
                SaveValue(xNode.CreateNavigator(), plist, p_Item);
            }
        }

        private void SaveValue(XPathNavigator p_XPathNav, SPList plist, SPListItem p_Item)
        {
            if (p_XPathNav != null)
            {
                string uniquePrefix = string.Format("{0}_{1}_", plist.Title, _ctypeName).Replace(" ", "_");
                string localName = p_XPathNav.LocalName.Replace(uniquePrefix, "");

                //begin looping through the nodes
                if (localName != null && localName != "ID")
                {
                    string mFieldInternalName = localName;
                    if (plist.Fields.ContainsField(mFieldInternalName))
                    {
                        SPField mField = plist.Fields.GetField(mFieldInternalName);
                        SPFieldType mFieldType = mField.Type;
                        //单独处理CheckBox
                        if (mFieldType.Equals(SPFieldType.Boolean))
                        {
                            if (!string.IsNullOrEmpty(p_XPathNav.Value))
                            {
                                p_Item[mField.Id] = Convert.ToBoolean(p_XPathNav.Value);
                            }
                            else
                            {
                                p_Item[mField.Id] = false;
                            }
                            //p_Item.SystemUpdate();
                        }
                        else if (!string.IsNullOrEmpty(p_XPathNav.Value))
                        {
                            if (mFieldType.Equals(SPFieldType.MultiChoice))
                            {
                                if (p_XPathNav.MoveToFirstChild())
                                {
                                    SPFieldMultiChoiceValue values = new SPFieldMultiChoiceValue();
                                    do
                                    {
                                        string fieldvalue = p_XPathNav.Value;
                                        if (!string.IsNullOrEmpty(fieldvalue))
                                        {
                                            values.Add(fieldvalue);
                                        }
                                    }
                                    while (p_XPathNav.MoveToNext());
                                    p_Item[mField.Id] = values;
                                    //p_Item.SystemUpdate();
                                }
                            }
                            else if (mFieldType.Equals(SPFieldType.Note))
                            {
                                object mFieldValue = GetFieldValueByType(mFieldType, p_XPathNav.InnerXml);
                                p_Item[mField.Id] = mFieldValue;
                                //p_Item.SystemUpdate();
                            }
                            else if (mFieldType.Equals(SPFieldType.User))
                            {
                                _xNameSpace.AddNamespace("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                                SPFieldUserValueCollection uvc = new SPFieldUserValueCollection();
                                if (p_XPathNav.HasChildren)
                                {
                                    SPSecurity.RunWithElevatedPrivileges(delegate
                                    {
                                        using (SPSite site = new SPSite(_siteName))
                                        {
                                            using (SPWeb web = site.OpenWeb(_webName))
                                            {
                                                p_XPathNav.MoveToFirstChild();
                                                do
                                                {
                                                    XPathNavigator nav = p_XPathNav.SelectSingleNode("./pc:AccountId", _xNameSpace);
                                                    if (nav != null)
                                                    {
                                                        SPUser user = (SPUser)GetFieldValueByType(mFieldType, nav.Value);
                                                        uvc.Add(new SPFieldUserValue(web, user.ID, user.Name));
                                                    }
                                                }
                                                while (p_XPathNav.MoveToNext());
                                            }
                                        }
                                    });
                                    p_Item[mField.Id] = uvc;
                                    //p_Item.SystemUpdate();
                                }
                                else
                                {
                                    p_Item[mField.Id] = "";
                                    //p_Item.SystemUpdate();
                                }
                                //XPathNavigator nav = p_xPathNav.SelectSingleNode("./pc:Person/pc:AccountId", xNameSpace);
                                //while (nav.MoveToFirstChild())
                                //{
                                //    //p_xPathNav.MoveToChild("AccountId", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                                //    object m_field_value = GetFieldValueByType(m_field_type, nav.Value);
                                //    p_item[m_field.Id] = m_field_value;
                                //    p_item.Update();
                                //}
                            }
                            else
                            {
                                object mFieldValue = GetFieldValueByType(mFieldType, p_XPathNav.Value);
                                p_Item[mField.Id] = mFieldValue;
                                //p_Item.SystemUpdate();
                            }
                        }
                    }
                }
            }
        }

        //通过SPField的Type，返回不同的对象，给Item的属性赋值。
        private object GetFieldValueByType(SPFieldType p_Field_Type, string p_Str_Value)
        {
            object mFieldValue = null;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite site = new SPSite(_siteName))
                {
                    using (SPWeb web = site.OpenWeb(_webName))
                    {
                        web.AllowUnsafeUpdates = true;
                        switch (p_Field_Type)
                        {
                            case SPFieldType.Text:
                                mFieldValue = p_Str_Value;
                                break;
                            case SPFieldType.User:
                                try
                                {
                                    SPUser mUser = web.EnsureUser(p_Str_Value);
                                    mFieldValue = mUser;
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.ToString());
                                }
                                break;
                            case SPFieldType.Integer:
                                int mInteger = int.Parse(p_Str_Value);
                                mFieldValue = mInteger;
                                break;
                            case SPFieldType.Number:
                                double mNumber = double.Parse(p_Str_Value);
                                mFieldValue = mNumber;
                                break;
                            case SPFieldType.Lookup:
                                SPFieldLookupValue mLookupValue = new SPFieldLookupValue(p_Str_Value);
                                mFieldValue = mLookupValue;
                                break;
                            case SPFieldType.Boolean:
                                mFieldValue = Convert.ToBoolean(p_Str_Value);
                                break;
                            case SPFieldType.Note:
                                string mString = Convert.ToString(p_Str_Value);
                                mString = FormatXhtmlString(mString);
                                mFieldValue = mString;
                                break;
                            default:
                                mFieldValue = p_Str_Value;
                                break;
                        }
                    }
                }
            });

            return mFieldValue;
        }

        private static string FormatXhtmlString(string m_String)
        {
            while (m_String.Contains("/>"))
            {
                int firstIndex = m_String.IndexOf("/>", StringComparison.Ordinal);
                string subMString = m_String.Substring(0, firstIndex);
                string subMStringLater = m_String.Substring(firstIndex + 2);
                int lastIndex = subMString.LastIndexOf("<", StringComparison.Ordinal) + 1;
                int spaceIndex = subMString.IndexOf(" ", lastIndex, StringComparison.Ordinal);
                string tagName = subMString.Substring(lastIndex, spaceIndex - lastIndex);
                subMString = subMString + "></" + tagName + ">";
                m_String = subMString + subMStringLater;

            }
            //m_string = m_string.Replace("\r\n", "<BR>");
            return m_String;
        }
        #endregion
    }
}
